package com.atguigu.tingshu.common.config;

import com.atguigu.tingshu.common.constant.RabbitConstant;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.lang.Nullable;

@Configuration
@Slf4j
public class RabbitConfig {

    @Autowired
    private RabbitTemplate rabbitTemplate;


    @PostConstruct
    public void init(){
        // 确认消息是否到达交换机，无论是否到达都会执行
        this.rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
            if (!ack){
                log.error("消息没有到达交换机。原因：{}", cause);
            }
        });
        // 确认消息是否到达队列，只有未到达队列才会执行
        this.rabbitTemplate.setReturnsCallback(returned -> {
            log.error("消息没有到达队列。交换机：{}，路由键：{}，消息：{}",
                    returned.getExchange(), returned.getRoutingKey(), new String(returned.getMessage().getBody()));
        });
    }




    /*
        创建 延迟队列 交换机 绑定
            原理：
                给一个队列设置过期时间，不使用消费者消费该队列的消息
                给队列绑定死信队列(死信交换机+死信路由key)

                使用消费者消费死信队列中的消息

                最后：消息发送到延迟队列 会在消息过期时消费 达到延迟的目的
     */

    //  交换机
    @Bean
    public Exchange cancelOrderExchange(){
        return ExchangeBuilder
                .topicExchange(RabbitConstant.ORDER_EXCHANGE)
                .durable(true)
                .build();
    }
    @Bean
    // 延迟队列
    public Queue cancelOrderQueue(){
        //延迟队列
        //死信： 设置过期时间 超时未消费的消息、超过队列长度 大小存储不下的消息、主动丢弃的消息
        return QueueBuilder
                .durable(RabbitConstant.ORDER_TTL_QUEUE)
                .ttl(15*60*1000) //15分钟的过期时间
                .deadLetterExchange(RabbitConstant.ORDER_EXCHANGE)
                .deadLetterRoutingKey(RabbitConstant.ORDER_DEAD_RK)
                .build();
    }
    @Bean
    // 绑定队列到交换机
    public Binding cancelOrderBinding(Exchange cancelOrderExchange , Queue cancelOrderQueue){
        return BindingBuilder
                .bind(cancelOrderQueue)
                .to(cancelOrderExchange)
                .with(RabbitConstant.ORDER_TTL_RK)
                .noargs();
    }
    // 发送消息时， 消息 rk(ORDER_TTL_RK) -> ORDER_EXCHANGE -> ORDER_TTL_QUEUE

    //死信队列+(绑定)
    @Bean
    public Queue deadOrderQueue(){
        //死信队列
        return QueueBuilder
                .durable(RabbitConstant.ORDER_DEAD_QUEUE)
                .build();
    }

    // (死信队列)+绑定
    @Bean
    public Binding deadOrderBinding(Exchange cancelOrderExchange ,Queue deadOrderQueue ){
        return BindingBuilder
                .bind(deadOrderQueue)
                .to(cancelOrderExchange)
                .with(RabbitConstant.ORDER_DEAD_RK)
                .noargs();
    }
}
